<template>
    <div class="ocr-container">
        <!-- 应用标题 -->
        <div class="app-header">
            <h1>Learning - 图片文字提取工具</h1>
            <p class="slogan">轻松提取图片中的文字，支持中英文混合识别</p>
        </div>

        <!-- 上传区域 -->
        <div class="upload-section">
            <el-upload class="upload-area" action="" :auto-upload="false" :on-change="handleFileSelect"
                :before-upload="beforeUploadCheck" :show-file-list="false" accept="image/*">
                <div class="upload-box">
                    <UploadFilled class="upload-icon" />
                    <div class="upload-text">
                        <p class="main-text">点击或拖拽图片到此处上传</p>
                        <p class="sub-text">支持JPG、PNG、BMP格式，大小不超过10MB</p>
                    </div>
                </div>
            </el-upload>

            <!-- 已选择文件预览 -->
            <div class="selected-file" v-if="selectedFileName">
                <Document class="file-icon" />
                <span>{{ selectedFileName }}</span>
                <el-button type="text" class="remove-btn" @click="clearFile" size="small">
                    <Close class="close-icon" />
                </el-button>
                <el-button type="primary" class="start-btn" @click="startRecognition" :loading="isProcessing"
                    size="small">
                    {{ isProcessing ? '识别中...' : '开始识别' }}
                </el-button>
            </div>

            <!-- 图片预览 -->
            <div class="image-preview" v-if="imagePreviewUrl">
                <el-image :src="imagePreviewUrl" alt="图片预览" fit="contain" :preview-teleported="true">
                    <template #error>
                        <div class="image-error">图片加载失败</div>
                    </template>
                </el-image>
            </div>
        </div>

        <!-- 结果展示区域 -->
        <div class="result-section" v-if="ocrResult">
            <div class="result-header">
                <h2>识别结果</h2>
                <el-button type="success" icon="CopyDocument" @click="copyToClipboard" size="small">
                    复制文本
                </el-button>
            </div>
            <div class="result-content">
                <div v-html="formatOcrResult(ocrResult)"></div>
            </div>
        </div>

        <!-- 历史记录区域 - 带滚动条 -->
        <div class="history-section" v-if="historyList.length > 0">
            <h3>识别历史</h3>
            <div class="history-scroll-container">
                <div class="history-items">
                    <div v-for="(item, index) in historyList" :key="index" class="history-item"
                        :class="{ 'active': activeHistoryIndex === index }" @click="loadHistoryItem(item, index)">
                        <div class="history-item-header">
                            <Document class="history-icon" />
                            <span class="history-filename">{{ item.fileName }}</span>
                            <el-button type="text" class="history-remove-btn" @click.stop="removeHistoryItem(index)"
                                size="small">
                                <Close class="close-icon" />
                            </el-button>
                        </div>
                        <div class="history-time">{{ formatDate(item.time) }}</div>
                        <div class="history-preview">{{ item.content.substring(0, 50) }}...</div>
                    </div>
                </div>
            </div>
        </div>
    </div>
</template>

<script setup lang="ts">
import { ref, onMounted } from 'vue';
import { ElMessage, ElLoading } from 'element-plus';
import { UploadFilled, Document, Close } from '@element-plus/icons-vue';
import { uploadRequest } from '@/utils/request';

interface RecognitionHistory {
    time: Date;
    content: string;
    fileName: string;
    previewUrl: string;
}

// 状态管理
const selectedFile = ref<File | null>(null);
const selectedFileName = ref('');
const imagePreviewUrl = ref('');
const isProcessing = ref(false);
const ocrResult = ref('');
const historyList = ref<RecognitionHistory[]>([]);
const activeHistoryIndex = ref<number | null>(null);

// 文件类型验证方法
const beforeUploadCheck = (file: File) => {
    const validTypes = ['image/png', 'image/jpeg', 'image/bmp'];
    const isImage = validTypes.includes(file.type);
    const isJpeg = file.type === 'image/jpeg' &&
        (file.name.toLowerCase().endsWith('.jpg') ||
            file.name.toLowerCase().endsWith('.jpeg'));

    if (!isImage || (file.type === 'image/jpeg' && !isJpeg)) {
        ElMessage.error('仅支持PNG、JPG/JPEG和BMP格式的图片');
        return false;
    }
    return true;
};

// 格式化OCR结果
const formatOcrResult = (result: string) => {
    if (!result) return '';
    return result
        .replace(/\n/g, '<br>')
        .replace(/\r/g, '')
        .replace(/ /g, '&nbsp;');
};

// 处理文件选择
const handleFileSelect = (file: any) => {
    const reader = new FileReader();
    reader.onload = (e) => {
        const img = new Image();
        img.onload = () => {
            if (img.width > 5000 || img.height > 5000) {
                ElMessage.warning('图片尺寸过大，建议缩小后上传');
            }
            selectedFile.value = file.raw;
            selectedFileName.value = file.name;
            ocrResult.value = '';
            imagePreviewUrl.value = URL.createObjectURL(file.raw);
        };
        img.onerror = () => {
            ElMessage.error('图片加载失败，文件可能已损坏');
            clearFile();
        };
        img.src = e.target?.result as string;
    };
    reader.readAsDataURL(file.raw);
};

// 清除已选择文件
const clearFile = () => {
    selectedFile.value = null;
    selectedFileName.value = '';
    ocrResult.value = '';
    if (imagePreviewUrl.value) {
        URL.revokeObjectURL(imagePreviewUrl.value);
        imagePreviewUrl.value = '';
    }
};

// 开始OCR识别
const startRecognition = async () => {
    if (!selectedFile.value) {
        ElMessage.warning('请先选择图片文件');
        return;
    }

    const formData = new FormData();
    formData.append('file', selectedFile.value);

    try {
        isProcessing.value = true;
        const loading = ElLoading.service({
            lock: true,
            text: '正在识别文字，请稍候...',
            background: 'rgba(0, 0, 0, 0.7)'
        });

        const result = await uploadRequest<string>({
            url: '/api/ocr/extract',
            method: 'post',
            data: formData,
        });

        ocrResult.value = result;
        saveToHistory(selectedFileName.value, result);
        ElMessage.success('识别成功！');
        loading.close();
    } catch (error) {
        console.error('识别失败:', error);
        ElMessage.error('识别失败，请重试');
    } finally {
        isProcessing.value = false;
    }
};

// 复制结果到剪贴板
const copyToClipboard = () => {
    if (!ocrResult.value) return;

    navigator.clipboard.writeText(ocrResult.value)
        .then(() => ElMessage.success('已复制到剪贴板'))
        .catch(() => {
            const textarea = document.createElement('textarea');
            textarea.value = ocrResult.value;
            document.body.appendChild(textarea);
            textarea.select();
            document.execCommand('copy');
            document.body.removeChild(textarea);
            ElMessage.success('已复制到剪贴板');
        });
};

// 保存到历史记录
const saveToHistory = (fileName: string, content: string) => {
    const newRecord: RecognitionHistory = {
        time: new Date(),
        fileName,
        content,
        previewUrl: imagePreviewUrl.value || '',
    };

    historyList.value.unshift(newRecord);
    if (historyList.value.length > 10) historyList.value.pop();

    localStorage.setItem('ocrHistory', JSON.stringify(
        historyList.value.map(item => ({
            ...item,
            time: item.time.toISOString()
        }))
    ));
};

// 加载历史记录项
const loadHistoryItem = (item: RecognitionHistory, index: number) => {
    activeHistoryIndex.value = index;
    ocrResult.value = item.content;
    selectedFileName.value = item.fileName;
    imagePreviewUrl.value = item.previewUrl;
};

// 删除历史记录项
const removeHistoryItem = (index: number) => {
    historyList.value.splice(index, 1);
    localStorage.setItem('ocrHistory', JSON.stringify(
        historyList.value.map(item => ({
            ...item,
            time: item.time.toISOString()
        }))
    ));

    if (activeHistoryIndex.value === index) {
        activeHistoryIndex.value = null;
        ocrResult.value = '';
        selectedFileName.value = '';
        imagePreviewUrl.value = '';
    }

    ElMessage.success('历史记录已删除');
};

// 格式化日期时间
const formatDate = (date: Date): string => {
    return new Intl.DateTimeFormat('zh-CN', {
        year: 'numeric',
        month: '2-digit',
        day: '2-digit',
        hour: '2-digit',
        minute: '2-digit',
    }).format(date);
};

// 初始化加载历史记录
onMounted(() => {
    try {
        const savedHistory = localStorage.getItem('ocrHistory');
        if (savedHistory) {
            const parsedHistory = JSON.parse(savedHistory) as any[];
            historyList.value = parsedHistory.map(item => ({
                ...item,
                time: new Date(item.time)
            }));
        }
    } catch (error) {
        console.error('加载历史记录失败:', error);
        localStorage.removeItem('ocrHistory');
    }
});
</script>

<style scoped>
.ocr-container {
    max-width: 800px;
    margin: 0 auto;
    padding: 20px;
    color: #333;
}

/* 应用标题 */
.app-header {
    text-align: center;
    margin: 20px 0 40px;
}

.app-header h1 {
    color: #303133;
    margin-bottom: 10px;
    font-size: 24px;
    font-weight: 500;
}

.app-header .slogan {
    color: #606266;
    font-size: 14px;
}

/* 上传区域 */
.upload-section {
    margin-bottom: 30px;
}

.upload-area {
    width: 100%;
}

.upload-box {
    border: 2px dashed #c0c4cc;
    border-radius: 8px;
    padding: 40px 20px;
    text-align: center;
    transition: all 0.3s;
    cursor: pointer;
    background-color: #fafafa;
}

.upload-box:hover {
    border-color: #409eff;
    background-color: #f5f7fa;
}

.upload-icon {
    font-size: 48px;
    color: #c0c4cc;
    margin-bottom: 20px;
}

.upload-text .main-text {
    font-size: 18px;
    color: #303133;
    margin-bottom: 8px;
    font-weight: 500;
}

.upload-text .sub-text {
    font-size: 14px;
    color: #909399;
}

/* 已选择文件 */
.selected-file {
    display: flex;
    align-items: center;
    padding: 12px;
    background-color: #f5f7fa;
    border-radius: 4px;
    margin-top: 16px;
    font-size: 14px;
    border: 1px solid #e4e7ed;
}

.selected-file .file-icon {
    color: #409eff;
    margin-right: 10px;
    font-size: 16px;
}

.selected-file span {
    flex: 1;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    margin-right: 10px;
}

.selected-file .remove-btn {
    color: #909399;
    margin-left: 5px;
}

.selected-file .close-icon {
    font-size: 14px;
}

.selected-file .start-btn {
    margin-left: 10px;
}

/* 图片预览 */
.image-preview {
    margin-top: 16px;
    border-radius: 4px;
    overflow: hidden;
    max-height: 300px;
    border: 1px solid #e4e7ed;
}

.image-preview .el-image {
    width: 100%;
    height: 300px;
    background-color: #f5f5f5;
}

.image-preview .image-error {
    width: 100%;
    height: 300px;
    display: flex;
    align-items: center;
    justify-content: center;
    color: #f56c6c;
    background-color: #fef0f0;
}

/* 结果展示区域 */
.result-section {
    margin-top: 30px;
    border: 1px solid #e4e7ed;
    border-radius: 8px;
    overflow: hidden;
    background-color: #fff;
}

.result-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 15px 20px;
    background-color: #f5f7fa;
    border-bottom: 1px solid #e4e7ed;
}

.result-header h2 {
    margin: 0;
    font-size: 16px;
    color: #303133;
    font-weight: 500;
}

.result-content {
    padding: 20px;
    max-height: 400px;
    overflow-y: auto;
    font-family: 'Menlo', 'Monaco', 'Consolas', monospace;
    line-height: 1.6;
    background-color: #f8f8f8;
    color: #333;
}

.result-content :deep(br) {
    content: "";
    display: block;
    margin-bottom: 0.5em;
}

/* 历史记录区域 */
.history-section {
    margin-top: 30px;
}

.history-section h3 {
    font-size: 16px;
    margin-bottom: 15px;
    color: #303133;
    font-weight: 500;
}

.history-section .el-timeline {
    padding-left: 20px;
}

.history-section .history-content {
    color: #606266;
    font-size: 14px;
    line-height: 1.5;
    margin-bottom: 10px;
}

/* 响应式适配 */
@media (max-width: 768px) {
    .ocr-container {
        padding: 15px;
    }

    .upload-box {
        padding: 30px 10px;
    }

    .result-content {
        padding: 15px;
        max-height: 300px;
    }

    .selected-file {
        flex-wrap: wrap;
        gap: 10px;
    }

    .selected-file .start-btn {
        margin-left: auto;
    }
}

/* 历史记录区域样式 */
.history-section {
    margin-top: 30px;
    background-color: #fff;
    border-radius: 8px;
    padding: 20px;
    border: 1px solid #e4e7ed;
}

.history-section h3 {
    margin: 0 0 15px 0;
    font-size: 16px;
    color: #303133;
    font-weight: 500;
}

.history-scroll-container {
    max-height: 300px;
    overflow-y: auto;
    padding-right: 8px;
}

/* 滚动条样式 */
.history-scroll-container::-webkit-scrollbar {
    width: 6px;
}

.history-scroll-container::-webkit-scrollbar-track {
    background: #f1f1f1;
    border-radius: 3px;
}

.history-scroll-container::-webkit-scrollbar-thumb {
    background: #c1c1c1;
    border-radius: 3px;
}

.history-scroll-container::-webkit-scrollbar-thumb:hover {
    background: #a8a8a8;
}

.history-items {
    display: flex;
    flex-direction: column;
    gap: 10px;
}

.history-item {
    padding: 12px;
    border-radius: 4px;
    border: 1px solid #e4e7ed;
    cursor: pointer;
    transition: all 0.2s;
}

.history-item:hover {
    background-color: #f5f7fa;
    border-color: #d3d6d8;
}

.history-item.active {
    background-color: #f0f7ff;
    border-color: #c6e2ff;
}

.history-item-header {
    display: flex;
    align-items: center;
    margin-bottom: 6px;
}

.history-icon {
    color: #909399;
    margin-right: 8px;
    font-size: 16px;
}

.history-filename {
    flex: 1;
    font-size: 14px;
    color: #303133;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.history-remove-btn {
    color: #909399;
    margin-left: 8px;
}

.history-time {
    font-size: 12px;
    color: #909399;
    margin-bottom: 6px;
}

.history-preview {
    font-size: 13px;
    color: #606266;
    line-height: 1.5;
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
    text-overflow: ellipsis;
}

/* 响应式适配 */
@media (max-width: 768px) {
    .history-scroll-container {
        max-height: 250px;
    }

    .history-item {
        padding: 10px;
    }
}
</style>